﻿using System;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ServiceApp
{
    /// <summary>
    /// 管道通信服务端 (.NET 8 兼容版)
    /// </summary>
    public class NamedPipeService : IDisposable
    {
        private const int MaxServerInstances = 10;
        private readonly string _pipeName;
        private NamedPipeServerStream? _pipeServer;
        private CancellationTokenSource? _cts;
        private bool _disposed;
        private bool _isRunning;

        /// <summary>
        /// 当前连接状态
        /// </summary>
        public bool IsConnected => _pipeServer?.IsConnected == true;

        /// <summary>
        /// 服务是否正在运行
        /// </summary>
        public bool IsRunning => _isRunning;

        /// <summary>
        /// 当客户端连接时触发
        /// </summary>
        public event EventHandler? Connected;

        /// <summary>
        /// 当客户端断开连接时触发
        /// </summary>
        public event EventHandler? Disconnected;

        /// <summary>
        /// 当接收到消息时触发
        /// </summary>
        public event EventHandler<string>? MessageReceived;

        /// <summary>
        /// 当发生错误时触发
        /// </summary>
        public event EventHandler<Exception>? ErrorOccurred;

        public NamedPipeService(string pipeName)
        {
            _pipeName = pipeName ?? throw new ArgumentNullException(nameof(pipeName));
        }

        /// <summary>
        /// 启动管道服务
        /// </summary>
        public async Task StartAsync()
        {
            if (_isRunning)
                throw new InvalidOperationException("服务已在运行");

            if (_disposed)
                throw new ObjectDisposedException(nameof(NamedPipeService));

            _cts = new CancellationTokenSource();
            _isRunning = true;

            try
            {
                _pipeServer = new NamedPipeServerStream(
                    _pipeName,
                    PipeDirection.InOut,
                    MaxServerInstances,
                    PipeTransmissionMode.Message,
                    PipeOptions.Asynchronous);

                await _pipeServer.WaitForConnectionAsync(_cts.Token);

                Connected?.Invoke(this, EventArgs.Empty);

                _ = Task.Run(() => ReceiveMessagesAsync(_cts.Token), _cts.Token);
            }
            catch (Exception ex) when (ex is not OperationCanceledException)
            {
                _isRunning = false;
                ErrorOccurred?.Invoke(this, ex);
                throw;
            }
        }

        /// <summary>
        /// 停止管道服务
        /// </summary>
        public void Stop()
        {
            if (!_isRunning) return;

            _cts?.Cancel();
            _cts?.Dispose();
            _cts = null;

            if (_pipeServer != null)
            {
                try
                {
                    if (_pipeServer.IsConnected)
                    {
                        _pipeServer.Disconnect();
                    }
                    _pipeServer.Close();
                    _pipeServer.Dispose();
                }
                catch { /* 忽略关闭时的异常 */ }
                finally
                {
                    _pipeServer = null;
                }
            }

            _isRunning = false;
            Disconnected?.Invoke(this, EventArgs.Empty);
        }

        /// <summary>
        /// 发送消息到客户端
        /// </summary>
        public async Task SendMessageAsync(string message)
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(NamedPipeService));

            if (_pipeServer == null || !_pipeServer.IsConnected)
                throw new InvalidOperationException("未连接到客户端");

            try
            {
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                await _pipeServer.WriteAsync(buffer, 0, buffer.Length);
                await _pipeServer.FlushAsync();
            }
            catch (Exception ex)
            {
                ErrorOccurred?.Invoke(this, ex);
                throw;
            }
        }

        private async Task ReceiveMessagesAsync(CancellationToken cancellationToken)
        {
            if (_pipeServer == null) return;

            var buffer = new byte[4096];

            try
            {
                while (!cancellationToken.IsCancellationRequested &&
                       _pipeServer.IsConnected)
                {
                    int bytesRead = await _pipeServer.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                    if (bytesRead == 0) break; // 客户端断开

                    string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    MessageReceived?.Invoke(this, message);
                }
            }
            catch (OperationCanceledException)
            {
                // 正常取消
            }
            catch (Exception ex)
            {
                ErrorOccurred?.Invoke(this, ex);
            }
            finally
            {
                Disconnected?.Invoke(this, EventArgs.Empty);
                Stop();
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed) return;

            if (disposing)
            {
                Stop();
                _cts?.Dispose();
            }

            _disposed = true;
        }

        ~NamedPipeService() => Dispose(false);
    }
}